#include <gtest/gtest.h>
#include "viml/parser.h"
#include "viml/ast_json_printer.h"
#include "viml/json_encoder.h"
#include <chrono>

namespace viml {

class ASTJsonPrinterTest : public ::testing::Test {
protected:
    void SetUp() override {}
    
    void TearDown() override {}
    
    // 辅助函数：检查JSON字符串是否包含特定值
    bool containsValue(const std::string& json, const std::string& value) {
        return json.find(value) != std::string::npos;
    }
    
    // 辅助函数：检查JSON字符串是否包含特定键
    bool containsKey(const std::string& json, const std::string& key) {
        std::string search_key = "\"" + key + "\":";
        return json.find(search_key) != std::string::npos;
    }
};

// 测试基本数字字面量的JSON输出
TEST_F(ASTJsonPrinterTest, BasicNumberLiteral) {
    std::string source = "42";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    EXPECT_TRUE(containsValue(json, "\"Program\""));
    EXPECT_TRUE(containsValue(json, "\"NumberLiteral\""));
    EXPECT_TRUE(containsValue(json, "42"));
}

// 测试字符串字面量的JSON输出
TEST_F(ASTJsonPrinterTest, StringLiteral) {
    std::string source = "\"hello world\"";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    EXPECT_TRUE(containsValue(json, "\"StringLiteral\""));
    EXPECT_TRUE(containsValue(json, "\"hello world\""));
}

// 测试二元表达式的JSON输出
TEST_F(ASTJsonPrinterTest, BinaryExpression) {
    std::string source = "a + b";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    EXPECT_TRUE(containsValue(json, "\"BinaryExpression\""));
    EXPECT_TRUE(containsValue(json, "\"+\""));
    EXPECT_TRUE(containsValue(json, "\"Identifier\""));
    EXPECT_TRUE(containsKey(json, "left"));
    EXPECT_TRUE(containsKey(json, "right"));
}

// 测试复杂嵌套结构
TEST_F(ASTJsonPrinterTest, ComplexNestedStructure) {
    std::string source = "let result = func(a + b, [1, 2, 3])";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    EXPECT_TRUE(containsValue(json, "\"LetStatement\""));
    EXPECT_TRUE(containsValue(json, "\"CallExpression\""));
    EXPECT_TRUE(containsValue(json, "\"BinaryExpression\""));
    EXPECT_TRUE(containsValue(json, "\"ListLiteral\""));
    EXPECT_TRUE(containsKey(json, "arguments"));
    EXPECT_TRUE(containsKey(json, "elements"));
}

// 测试函数定义的JSON输出
TEST_F(ASTJsonPrinterTest, FunctionDefinition) {
    std::string source = "function add(a, b)\nreturn a + b\nendfunction";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    EXPECT_TRUE(containsValue(json, "\"FunctionStatement\""));
    EXPECT_TRUE(containsValue(json, "\"add\""));
    EXPECT_TRUE(containsValue(json, "\"ReturnStatement\""));
    EXPECT_TRUE(containsKey(json, "parameters"));
    EXPECT_TRUE(containsKey(json, "body"));
}

// 测试条件语句的JSON输出
TEST_F(ASTJsonPrinterTest, IfStatement) {
    std::string source = "if x > 0\necho \"positive\"\nelse\necho \"negative\"\nendif";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    EXPECT_TRUE(containsValue(json, "\"IfStatement\""));
    EXPECT_TRUE(containsKey(json, "condition"));
    EXPECT_TRUE(containsKey(json, "then_body"));
    EXPECT_TRUE(containsKey(json, "else_body"));
}

// 测试Visitor模式的状态重置功能
TEST_F(ASTJsonPrinterTest, VisitorStateReset) {
    ASTJsonPrinter json_printer;
    
    // 第一次使用
    std::string source1 = "42";
    viml::Parser parser1(source1);
    auto program1 = parser1.parse();
    program1->accept(json_printer);
    std::string json1 = json_printer.get_json();
    
    // 重置状态
    json_printer.reset();
    
    // 第二次使用
    std::string source2 = "\"hello\"";
    viml::Parser parser2(source2);
    auto program2 = parser2.parse();
    program2->accept(json_printer);
    std::string json2 = json_printer.get_json();
    
    // 验证两次输出不同且都正确
    EXPECT_NE(json1, json2);
    EXPECT_TRUE(containsValue(json1, "42"));
    EXPECT_TRUE(containsValue(json2, "hello"));
}

// 性能对比测试：Visitor模式 vs 直接方法调用
TEST_F(ASTJsonPrinterTest, PerformanceComparison) {
    std::string source = R"(
        function fibonacci(n)
            if n <= 1
                return n
            else
                return fibonacci(n-1) + fibonacci(n-2)
            endif
        endfunction
        
        let result = fibonacci(10)
        echo result
    )";
    
    viml::Parser parser(source);
    auto program = parser.parse();
    
    // 测试Visitor模式性能
    auto start_visitor = std::chrono::high_resolution_clock::now();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string visitor_json = json_printer.get_json();
    
    auto end_visitor = std::chrono::high_resolution_clock::now();
    auto visitor_duration = std::chrono::duration_cast<std::chrono::microseconds>(end_visitor - start_visitor);
    
    // 测试直接方法调用性能
    auto start_direct = std::chrono::high_resolution_clock::now();
    
    std::string direct_json = program->to_json();
    
    auto end_direct = std::chrono::high_resolution_clock::now();
    auto direct_duration = std::chrono::duration_cast<std::chrono::microseconds>(end_direct - start_direct);
    
    // 输出性能对比信息
    std::cout << "性能对比:" << std::endl;
    std::cout << "  Visitor模式: " << visitor_duration.count() << " 微秒" << std::endl;
    std::cout << "  直接方法调用: " << direct_duration.count() << " 微秒" << std::endl;
    
    // 验证输出结果相同
    EXPECT_EQ(visitor_json, direct_json);
    
    // 确保性能在合理范围内（都应该小于10毫秒）
    EXPECT_LT(visitor_duration.count(), 10000);
    EXPECT_LT(direct_duration.count(), 10000);
}

// 测试JSON输出的格式正确性
TEST_F(ASTJsonPrinterTest, JSONFormatValidation) {
    std::string source = "let x = {\"key\": \"value\", \"number\": 42}";
    viml::Parser parser(source);
    auto program = parser.parse();
    
    ASTJsonPrinter json_printer;
    program->accept(json_printer);
    std::string json = json_printer.get_json();
    
    // 基本JSON格式检查
    EXPECT_TRUE(json.front() == '{');
    EXPECT_TRUE(json.back() == '}');
    
    // 确保包含必要的结构
    EXPECT_TRUE(containsValue(json, "\"DictLiteral\""));
    EXPECT_TRUE(containsKey(json, "pairs"));
    EXPECT_TRUE(containsKey(json, "key"));
    EXPECT_TRUE(containsKey(json, "value"));
}

} // namespace viml